package godb

import (
	"errors"
	"gitee.com/kinwyb/conv"
	"reflect"
	"strings"
)

type setMapVal interface {
	SetMapValue(data map[string]interface{})
}

// SetValueToStruct 设置值到Struct
func SetValueToStruct(obj interface{}, val map[string]interface{}) error {
	if v, ok := obj.(setMapVal); ok {
		v.SetMapValue(val)
		return nil
	}
	var vp reflect.Value
	if v, ok := obj.(reflect.Value); ok {
		vp = v
	} else {
		vp = reflect.ValueOf(obj)
		if vp.CanInterface() {
			vp = vp.Elem()
		}
	}
	if vp.Type().Kind() != reflect.Struct {
		return errors.New("只能转换内容到结构体")
	}
	rtype := reflect.TypeOf(vp.Interface())
	tp := fieldObj(rtype)
	for k, v := range tp {
		d := vp.FieldByName(k)
		if d.Type().Kind() == reflect.Struct { //如果是结构体则再次解析里面内容
			SetValueToStruct(d, val)
			continue
		}
		switch d.Type().String() {
		case "string":
			d.SetString(strings.TrimSpace(conv.ToString(val[v])))
		case "int8", "int16", "int32", "int", "int64":
			d.SetInt(conv.ToInt64(val[v]))
		case "float32", "float64":
			d.SetFloat(conv.ToFloat64(val[v]))
		case "bool":
			d.SetBool(conv.ToBool(val[v]))
		}
	}
	return nil
}

// fieldObj 解析对象结构
// @param tp reflect.Type 对象类型
// @param vname string 对象名称
func fieldObj(tp reflect.Type) map[string]string {
	x := tp.NumField()
	var field reflect.StructField
	var db string
	tag := map[string]string{}
	for i := 0; i < x; i++ {
		field = tp.Field(i)
		db = strings.Split(field.Tag.Get("db"), ",")[0]
		if db == "" {
			db = field.Name
		}
		tag[field.Name] = db
	}
	return tag
}
